package com.yimi.appstore.download;

import java.io.File;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;

import android.os.AsyncTask;
import android.util.Log;


public class DownloadTask {
	/** 更新进度最小需要下载的大小Byte*/
	private final int MIN_PROGRESS_STEP = 4096;
	/** 更新进度最小需要的时间间隔*/
	private final long MIN_PROGRESS_TIME = 1500;

	/** 正在初始化*/
	public final static int STATE_INIT = 0;
	/** 正在下载*/
	public final static int STATE_DOWNLOADING = 1;
	/** 停止*/
	public final static int STATE_STOP = 2;
	/** 仅删除任务*/
	public final static int STATE_DELETE = 3;
	/** 删除任务和文件*/
	public final static int STATE_DELETE_WITH_FILE = 4;
	/** 下载完成*/
	public final static int STATE_FINISH = 5;
	/** 下载失败*/
	public final static int STATE_FAIL = 6;
	
	private int mCurrentState = STATE_STOP;
	private DownloadEntry mDownloadEntry;

	private OnChangeListener mOnTaskChangeListener;
	private int mBytesNotified;
	private long mTimeLastNotification;
	private DownloadTask self;

	public DownloadTask(DownloadEntry downloadEntry) {
		mDownloadEntry = downloadEntry;
		self=this;
	}

	interface OnChangeListener{
		void onProgressUpdate(DownloadTask downloadTask);
		void onStateUpdate(int state,DownloadTask downloadTask);
	}
	
	/**
	 * 设置任务变化监听器
	 * @param onTaskChangeListener
	 */
	public void setOnTaskChangeListener(OnChangeListener onTaskChangeListener){
		mOnTaskChangeListener=onTaskChangeListener;
	}

	class DownloadAsyncTask extends AsyncTask<Void, Integer, Void> {
		private final int MSG_UPDATE_PROGRESS=1;
		private final int MSG_FORCE_UPDATE_PROGRESS=2;
		private final int MSG_UPDATE_STATE=0;
		@Override
		protected void onPreExecute() {
			super.onPreExecute();
			mCurrentState=STATE_INIT;
			mBytesNotified=0;
			mTimeLastNotification=0;
		}

		@Override
		protected Void doInBackground(Void... params) {
			publishProgress(MSG_UPDATE_STATE);
			File file= new File(mDownloadEntry.getPath());
			try {
				URL url = new URL(mDownloadEntry.getUrl());
				HttpURLConnection conn = (HttpURLConnection) url
						.openConnection();
				conn.setRequestProperty("Range",
						"bytes=" + mDownloadEntry.getCurrentBytes() + "-");
				int totalBytes = mDownloadEntry.getCurrentBytes()
						+ conn.getContentLength();
				mDownloadEntry.setTotalBytes(totalBytes);
				InputStream input = conn.getInputStream();
				RandomAccessFile raf = new RandomAccessFile(file, "rwd");
				raf.seek(mDownloadEntry.getCurrentBytes());
				byte[] buffer = new byte[8192];
				int read = 0;
				if(mCurrentState==STATE_INIT){
					mCurrentState = STATE_DOWNLOADING;
					publishProgress(MSG_UPDATE_STATE);
				}
				while ((read = input.read(buffer)) != -1) {
					synchronized (this) {
						switch (mCurrentState) {
						case STATE_DOWNLOADING:
							mDownloadEntry.setCurrentBytes(mDownloadEntry.getCurrentBytes()+read);
							raf.write(buffer, 0, read);
							publishProgress(MSG_UPDATE_PROGRESS);
							break;
						case STATE_STOP:
							publishProgress(MSG_FORCE_UPDATE_PROGRESS);
							publishProgress(MSG_UPDATE_STATE);
							return null;
						case STATE_DELETE_WITH_FILE:
							file.delete();
							publishProgress(MSG_UPDATE_STATE);
						case STATE_DELETE:
							publishProgress(MSG_UPDATE_STATE);
							return null;
						}
					}
				}
				raf.close();
				publishProgress(MSG_FORCE_UPDATE_PROGRESS);
				mCurrentState = STATE_FINISH;
				publishProgress(MSG_UPDATE_STATE);
			} catch (Exception e) {
				mCurrentState = STATE_FAIL;
				publishProgress(MSG_UPDATE_STATE);
			}
			return null;
		}
		
		@Override
		protected void onProgressUpdate(Integer... values) {
			switch (values[0]) {
			case MSG_UPDATE_STATE:
				Log.e("downloadtask", mDownloadEntry.getId()+" task state "+mCurrentState);
				mOnTaskChangeListener.onStateUpdate(mCurrentState, self);
				break;
			case MSG_UPDATE_PROGRESS:
				reportProgress(false);
				break;
			case MSG_FORCE_UPDATE_PROGRESS:
				reportProgress(true);
			}
			super.onProgressUpdate(values);
		}
	}
	
	/**
	 * 回调报告下载的进度
	 * @param force
	 */
	private void reportProgress(boolean force){
		long now = System.currentTimeMillis();
		if (force||(mDownloadEntry.getCurrentBytes() - mBytesNotified > MIN_PROGRESS_STEP
				&& now - mTimeLastNotification > MIN_PROGRESS_TIME) ){
			mBytesNotified = mDownloadEntry.getCurrentBytes();
			mDownloadEntry.setLastMod(now);
			mTimeLastNotification = now;
			mOnTaskChangeListener.onProgressUpdate(self);
		}
	}
	
	/**
	 * 获得该任务的下载实体
	 * @return
	 */
	public DownloadEntry getDownloadEntry(){
		return mDownloadEntry;
	}
	
	/**
	 * 获得任务状态
	 * @return
	 */
	public int getState(){
		return mCurrentState;
	}
	
	/**
	 * 仅删除任务
	 */
	public void delete(){
		if(mCurrentState!=STATE_DOWNLOADING){
			mOnTaskChangeListener.onStateUpdate(STATE_DELETE, self);
		}
		mCurrentState=STATE_DELETE;
	}
	
	/**
	 * 删除任务和文件
	 */
	public synchronized void deleteWithFile(){
		if(mCurrentState!=STATE_DOWNLOADING){
			mOnTaskChangeListener.onStateUpdate(STATE_DELETE_WITH_FILE, self);
		}
		mCurrentState=STATE_DELETE_WITH_FILE;
	}
	
	/**
	 * 开始任务
	 */
	public void start(){
		new DownloadAsyncTask().execute();
	}
	/**
	 * 停止任务
	 */
	public void stop(){
		mCurrentState=STATE_STOP;
	}
	
	/**
	 * 重启任务
	 */
	public void restart(){
		start();
	}
}
